<?php
/**
 * Глобальный класс управления страницами в контроллерах
 * 
 * @category Phorm
 * @package Page
 * @name /Phorm/Page.php
 * @copyright phorm.ru
 * @since 19.09.2012
 * @author vladimir@kachalov.net
 */

class Phorm_Page extends Phorm_Model {
	
	/**
	 * Имя контроллера
	 * @var string
	 */
	private $_controller = 'page';
	
	/**
	 * Локальный конструктор
	 *
	 * @return void
	 */
	
	public function init() {
		
		$this->_controller = $this->_params['controller'];
		
	}
	
	/**
	 * Устанавливает текущий контроллер
	 *
	 * @param string $controllername
	 * @return void
	 */
	
	public function setController($controllername) {
		
		$this->_controller = strtolower($controllername);
		
	}
	
	/**
	 * Возвращает текущий контроллер
	 *
	 * @return void
	 */
	
	public function getController() {
		
		return $this->_controller;
		
	}
	
	/**
	 * Возвращает список страниц
	 *
	 * @param array $options Массив условий для выборки
	 * @return array
	 */
	
	public function getPageList($options = array()) {
		
		$tableCols = $this->getTableCols('pw_pages');
		
		$select = $this->_db->select()
				-> from(array('AA'=>'pw_pages'), new Zend_Db_Expr('SQL_CALC_FOUND_ROWS AA.*, 1 actions'))
				-> where('isexist=?','yes')
				-> where('controllername=?',$this->getController());
				
		if($this->getModule()!=='control') $select -> where('visible=?','yes');
		
		// Другие условия для выборки
		foreach ($options as $optionname=>$optionvalue) {
			if(in_array($optionname,$tableCols)) {
				$select -> where($optionname . '=?', $optionvalue);
			}
		}
		
		// Сортировки
		if(isset($options['sortField']) && in_array($options['sortField'],$tableCols)) {
			$sortOrder = isset($options['sortOrder']) && $options['sortOrder']=='desc' ? ' DESC' : ' ASC';
			$select -> order($options['sortField'].$sortOrder);
		} else {
			$select -> order('IF(sortorder=0,999999999,sortorder)')
					-> order('pagename');
		}
		
		// Устанавливаем количество отдаваемых строк
		// Если передан 0, то возвращаем все найденные строки
		if (isset($options['rowsperpage']) && $options['rowsperpage']>0) {
			$select -> limitPage($this->getCurrentPage(),(int)$options['rowsperpage']);
		} elseif(!isset($options['rowsperpage'])) {
			$select -> limitPage($this->getCurrentPage(),$this->getPerPage());
		}
		
		return $this->_db->fetchAll($select);
		
	}
	
	/**
	 * Возвращает список страниц в виде меню
	 *
	 * @param int $active Id активной страницы
	 * @return Zend_Navigation
	 */
	
	public function getNavigationMenu($active = 0) {
		
		/*$menu = array(
			array(
				'id' => 0,
				'label' => 'Главная страница',
				'uri' => '#',
				'pages' => array()
			)
		);*/
		
		$pages = $this->getPageList();
		
		foreach ($pages as $page) {
			
			$menu[$page['pageid']] = array(
				'id' => $page['pageid'],
				'label' => $page['pagename'],
				'uri' => $this->_cnf['site']['url'] . '/control/' . $this->getController() . '/edit/pageid/' . $page['pageid'] . '/',
				'active' => $active == $page['pageid'] ? true : false,
				'class' => $page['visible']=='no' ? 'ui-state-disabled' : null
			);
			
		}
		
		return new Zend_Navigation($menu);
		
	}
	
	/**
	 * Возвращает информацию о странице
	 *
	 * @param string $identity Id или текстовый идентификатор страницы
	 * @return array
	 */
	
	public function getPageInfo($identity) {
		
		$select = $this->_db->select()
				-> from('pw_pages')
				-> where('isexist=?','yes')
				-> where('controllername=?',$this->getController())
				-> where('? IN(pageid,pageuid)',$identity);
				
		if($this->getModule()!=='control') $select -> where('visible=?','yes');
		
		return $this->_db->fetchRow($select);
		
	}
	
	/**
	 * Возвращает форму создания/редактирования страницы
	 *
	 * @param string $section Секция xml-файла
	 * @return Phorm_Form
	 * @todo Путь к форме должен зависеть от текущего контроллера... Подумать
	 */
	
	public function getPageForm($section = 'add') {
		
		$form = new Phorm_Form('forms/control/page.xml',$section);
		
		if($pageuid = $form->getElement('pageuid')) {
			$pageuid -> addValidator('Callback',true,
				array('callback' => array($this,'validateUid'), 
					  'messages' => array('callbackValue' => 'Такой идентификатор уже используется. Укажите другой')));
		}
		
		return $form;
		
	}
	
	/**
	 * Сохраняет данные формы создания/редактирования страницы
	 * 
	 * @param Phorm_Form $form Объект формы
	 * @param mixed $data Дополнительные данные формы. Если передана строка, то принимается как pageid
	 * 
	 * @return array | false
	 */
	
	public function savePageForm(Phorm_Form $form, $data = null) {
		
		/**
		 * Получаем значения формы и объединяем их с массивом дополнительных данных
		 */
		
		if(!is_null($data) && is_string($data)) $data = array('pageid'=>$data);
		$data = array_merge($form->getValues(),(array)$data);
		
		/**
		 * Предварительный фильтр значений
		 */
		
		$maindata = $this->getFilteredValuesByTableCols('pw_pages',$data);
		$maindata['controllername'] = $this->getController();
		
		/**
		 * Сохранение данных
		 */
		
		$this->_db->beginTransaction();
		
		try {
			
			// Изменение существующей записи
			
			if(isset($data['pageid'])) {
				
				$action = 'update';
				$this->_db->update('pw_pages',$maindata,'pageid='.(int)$data['pageid']);
				
			// Вставка новой записи
				
			} else {
				
				$action = 'insert';
				$this->_db->insert('pw_pages',$maindata);
				$data['pageid'] = $this->_db->lastInsertId();
				
			}
			
			/**
			 * Логирование
			 */
			$this->setLog($action,
				array('url' => '/control/page/edit/pageid/' . (int)$data['pageid'] . '/',
					  'name' => $data['pagename'],
					  'tablename' => 'pw_pages',
					  'identity' => (int)$data['pageid'],
					  'fieldname' => 'pageid'));
			
			$this->_db->commit();						  
			return $data;
			
		} catch (Exception $e) {
			
			$this->_db->rollBack();	
			$this->_errors[] = $e->getMessage();
			
		}
		
		return false;
		
	}
	
	/**
	 * Удаляет страницу
	 *
	 * @param array $PageInfo @see self::getPageInfo
	 * @return boolean
	 */
	
	public function deletePage($PageInfo) {
		
		$this->_db->beginTransaction();
		
		try {
		
			$this->_db->update('pw_pages',array('isexist'=>'no'), 'pageid=' . (int)$PageInfo['pageid']);
			
			/**
			 * Логирование
			 */
			$this->setLog('delete',
				array('url' => '/control/page/edit/pageid/' . (int)$PageInfo['pageid'] . '/',
					  'name' => $PageInfo['pagename'],
					  'tablename' => 'pw_pages',
					  'identity' => (int)$PageInfo['pageid'],
					  'fieldname' => 'pageid'));
			
			$this->_db->commit();
			
			return true;
		
		} catch (Exception $e) {
			
			$this->_db->rollBack();
			$this->_errors[] = $e->getMessage();
			
		}
		
		return false;
		
	}
	
	/**
	 * Генерирует идентификатор страницы на основе названия
	 *
	 * @param string $str Строка для модификации
	 * @return string
	 */
	
	public function getUidGenerated($str,$exclude = null) {
		
		$search = array('а','б','в','г','д','е','ё','ж','з','и','й','к','л','м','н','о','п','р','с','т','у','ф','х','ц','ч','ш','щ','ь','ы','ъ','э','ю','я');
		$replace = array('a','b','v','g','d','e','yo','zh','z','i','y','k','l','m','n','o','p','r','s','t','u','f','kh','c','ch','sh','sch','','i','','e','u','ya');
		$str = str_replace($search,$replace,trim(mb_strtolower($str)));
			
		$str = preg_replace('#[^-_\s0-9a-z]#u','',$str);
		$str = preg_replace('#\s+#u','_',$str);
		$str = substr($str,0,250);
		
		return $str;

	}
	
	/**
	 * Проверка существования pageuid
	 *
	 * @param str $uid
	 * @return bool
	 */
	
	public function validateUid($uid) {
		
		if(strtolower($uid) == 'index') return false;
		
		$select = $this->_db->select()
				-> from('pw_pages')
				-> where('isexist=?','yes')
				-> where('pageuid=?',(string)$uid)
				-> where('controllername=?',$this->getController());
		if(isset($this->_params['pageid'])) {
			$select -> where('pageid!=?',(int)$this->_params['pageid']);
		}
		
		return $this->_db->fetchOne($select) ? false : true;
		
	}
	
}

/**
 * @todo Некоторые наброски для будущего CRUD
 * 
 * $crud = new Phorm_Crud($config) // Массив конфигурации либо путь к xml-файлу настроек
 * 
 * Что из себя представляют настройки
 * 
 * table - имя таблицы
 * data - массив описания ключевых столбцов таблицы
 * 		identity - первичный ключ
 * 		fieldname - столбец в котором находится название материала
 * grid - Опции грида для вывода списка материалов
 * 		path - Путь к xml-файлу
 * 		section - Секция xml-файла
 * forms - Опции форм создания/редактирования (м.б. имеет смысл создавать единый файл настроек включая формы, гриды и настройки)
 * 		add - Форма создания
 * 			path - Путь к xml-файлу
 * 			section - Секция xml-файла
 * 		edit - Форма редактирования
 * 			path - Путь к xml-файлу
 * 			section - Секция xml-файла
 * cache - Настройки кеша (формат совместим с Zend application.xml)
 * messages - Массив информационных сообщений
 * 
 * По идее также как и со страницами мы расщиряем CRUD-контроллер нашим контроллером
 * Также мы можем отдельно использовать CRUD-модель, соответственно, CRUD-модель должна расширять Phorm_Model и инициализироваться в предиспетчере контроллера
 */